﻿using MbUnit.Framework;
using NEnsure.Validators;

namespace NEnsure.UnitTests
{
	[TestFixture]
	public class UsabilityTests
	{
		[Test]
		public void Test()
		{
			IValidator validator = new ManualValidator();

			RegisterRequest request = new RegisterRequest();

			request.Username = "Invalid Username";
			request.Password = " ";
			request.Email = "valid@email.com";
			request.ConfirmEmail = "not@same.com";
			request.AgreeToTOS = false;

			validator.Ensure("Username", request.Username).Satisfies(Rule.IsRequired, Rule.IsUsername, Rule.IsBrokenIf(UsernameInspector.UsernameIsInUse));
			validator.Ensure("Password", request.Password).Satisfies(Rule.IsRequired);
			validator.Ensure("Email", request.Email).Satisfies(Rule.IsRequired, Rule.IsEmail, Rule.IsBrokenIf(EmailInspector.EmailIsInUse));
			validator.Ensure("ConfirmEmail", request.ConfirmEmail).Satisfies(Rule.IsSameAs("Email", request.Email));
			validator.Ensure("AgreeToTOS", request.AgreeToTOS).Satisfies(Rule.GetEqualToRuleForType(true));

			validator.EnsureAll();

			Assert.AreEqual(5, validator.BrokenRules.Count);
			Assert.AreEqual(1, validator.BrokenRules.GetBrokenRulesForProperty("Username").Length);
			Assert.AreEqual(1, validator.BrokenRules.GetBrokenRulesForProperty("Password").Length);
			Assert.AreEqual(1, validator.BrokenRules.GetBrokenRulesForProperty("Email").Length);
			Assert.AreEqual(1, validator.BrokenRules.GetBrokenRulesForProperty("ConfirmEmail").Length);
			Assert.AreEqual(1, validator.BrokenRules.GetBrokenRulesForProperty("AgreeToTOS").Length);
		}

		private class UsernameInspector : IInspector<string>
		{
			public string ErrorFormat
			{
				get { return "{key} {value} is in use."; }
			}

			public static UsernameInspector UsernameIsInUse
			{
				get { return new UsernameInspector(); }
			}

			public bool Inspect(string value)
			{
				return value == "existing";
			}
		}

		private class EmailInspector : IInspector<string>
		{
			public string ErrorFormat
			{
				get { return "{key} {value} is in use."; }
			}

			public static EmailInspector EmailIsInUse
			{
				get { return new EmailInspector();}
			}

			public bool Inspect(string value)
			{
				return value == "valid@email.com";
			}
		}

		private class RegisterRequest
		{
			private string _username;
			private string _password;
			private string _email;
			private string _confirmEmail;
			private bool _agreeToTOS;

			public string Username
			{
				get { return _username; }
				set { _username = value; }
			}

			public string Password
			{
				get { return _password; }
				set { _password = value; }
			}

			public string Email
			{
				get { return _email; }
				set { _email = value; }
			}

			public string ConfirmEmail
			{
				get { return _confirmEmail; }
				set { _confirmEmail = value; }
			}

			public bool AgreeToTOS
			{
				get { return _agreeToTOS; }
				set { _agreeToTOS = value; }
			}
		}
	}
}
